{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "kxu1Gfhx1pHg"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/jeffheaton/app_generative_ai/blob/main/t81_559_class_10_1_streamlit.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ZbNbAV281pHh"
      },
      "source": [
        "# T81-559: Applications of Generative Artificial Intelligence\n",
        "**Module 10: StreamLit**\n",
        "* Instructor: [Jeff Heaton](https://sites.wustl.edu/jeffheaton/), McKelvey School of Engineering, [Washington University in St. Louis](https://engineering.wustl.edu/Programs/Pages/default.aspx)\n",
        "* For more information visit the [class website](https://sites.wustl.edu/jeffheaton/t81-558/)."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "HwnvSYEQ1pHi"
      },
      "source": [
        "# Module 10 Material\n",
        "\n",
        "Module 10: StreamLit\n",
        "\n",
        "* **Part 10.1: Running StreamLit in Google Colab** [[Video]]() [[Notebook]](t81_559_class_10_1_streamlit.ipynb)\n",
        "* Part 10.2: StreamLit Introduction [[Video]]() [[Notebook]](t81_559_class_10_2_streamlit_intro.ipynb)\n",
        "* Part 10.3: Understanding Streamlit State [[Video]]() [[Notebook]](t81_559_class_10_3_streamlit_state.ipynb)\n",
        "* Part 10.4: Creating a Chat Application [[Video]]() [[Notebook]](t81_559_class_10_4_chat.ipynb)\n",
        "* Part 10.5: MultiModal Chat Application [[Video]]() [[Notebook]](t81_559_class_10_5_chat_multimodal.ipynb)\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "XLFov09h18yC"
      },
      "source": [
        "# Google CoLab Instructions\n",
        "\n",
        "The following code ensures that Google CoLab is running and maps Google Drive if needed."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "AWGARRT92DrA"
      },
      "outputs": [],
      "source": [
        "import os\n",
        "\n",
        "try:\n",
        "    from google.colab import drive, userdata\n",
        "    COLAB = True\n",
        "    print(\"Note: using Google CoLab\")\n",
        "except:\n",
        "    print(\"Note: not using Google CoLab\")\n",
        "    COLAB = False\n",
        "\n",
        "# OpenAI Secrets\n",
        "if COLAB:\n",
        "    os.environ[\"OPENAI_API_KEY\"] = userdata.get('OPENAI_API_KEY')\n",
        "\n",
        "# Install needed libraries in CoLab\n",
        "if COLAB:\n",
        "    !pip install langchain openai streamlit"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "v2MPPX0c1pHi"
      },
      "source": [
        "# Part 10.1: Running StreamLit in Google Colab\n",
        "\n",
        "In this module, we will explore Streamlit, a powerful tool for building interactive web applications. Streamlit provides a simple and intuitive way to create user interfaces for our Generative AI applications, allowing users to interact with AI models in real-time. By using Streamlit, we can enhance the accessibility and usability of our AI solutions, making it easier to showcase results, accept user inputs, and visualize data—all through a web-based interface without requiring extensive web development knowledge.\n",
        "\n",
        "* [StreamLit](https://streamlit.io/)\n",
        "* [StreamLit Documentation](https://docs.streamlit.io/)\n",
        "\n",
        "Streamlit is an open-source Python library that makes it easy to create and share custom web applications for machine learning and data science projects. Designed with simplicity in mind, Streamlit allows developers to turn data scripts into interactive apps with just a few lines of code. It offers built-in components like sliders, buttons, text input, and charts that can be effortlessly integrated into an application. Streamlit automatically refreshes the app as the code is updated, providing an instant preview of changes. This makes it an ideal tool for quickly building and deploying interfaces for AI models, data visualizations, and various data science tasks.\n",
        "\n",
        "\n",
        "## Hello World StreamLit\n",
        "\n",
        "Next, we will look at a simple \"Hello, World!\" application in Streamlit to get a hands-on introduction to its functionality. This basic example will demonstrate how to create and run a Streamlit app using just a few lines of Python code. After building the app, we will explore how to deploy it using Google Colab, making it accessible through a web interface.\n",
        "\n",
        "We need to write an ``app.py`` file, and we do that with the line ``%%writefile app.py``, which is a magic command used in environments like Jupyter Notebook to create and save the code into a new file named ``app.py``. In the script, the import streamlit as st statement imports the Streamlit library and assigns it the alias st for easier usage. The line ``st.write(\"Hello World\")`` is a simple command in Streamlit that outputs the text \"Hello World\" to the application interface. When this script is executed using Streamlit, it launches a web app that displays the message \"Hello World,\" serving as a basic example of how Streamlit can create a user interface."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "q-HB2MnV5Fhb"
      },
      "outputs": [],
      "source": [
        "%%writefile app.py\n",
        "import streamlit as st\n",
        "\n",
        "st.write(\"Hello World\")"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "\n",
        "In this module, we will use npx to create a secure tunnel to the Streamlit server running in our Google Colab environment. Since Colab operates in a remote environment without direct access to localhost, tunneling allows us to expose the Streamlit app to the web, enabling us to interact with it. To establish this tunnel, we will use the below command to retrieve the necessary password. This password corresponds to the IP address of the Colab node on which our Streamlit server is running. By using this IP address, we can authenticate our connection through the tunnel, providing a secure pathway to access the Streamlit app from our local browser."
      ],
      "metadata": {
        "id": "MnAV_bNbYDdX"
      }
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "pp9t944r3hm8"
      },
      "outputs": [],
      "source": [
        "!curl https://loca.lt/mytunnelpassword"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "Next we launch StreamLit to run in the background of our CoLab instance."
      ],
      "metadata": {
        "id": "In8q5jmZcY_o"
      }
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "TDddusH22OKo"
      },
      "outputs": [],
      "source": [
        "!streamlit run app.py &>/content/logs.txt &"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "We are now ready to start the tunnel, you will be given a URL to access your StreamLit app, you will need to enter the password/ip address you previously obtained. This command will continue to run until you stop it."
      ],
      "metadata": {
        "id": "l_4oECKMcdtp"
      }
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "c0tTbyVC2SMp"
      },
      "outputs": [],
      "source": [
        "!npx localtunnel --port 8501"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Simple StreamLit Input\n",
        "\n",
        "Now, we will look at an example that demonstrates how to accept and evaluate a mathematical expression from the user through a simple interface. The following code creates a basic Streamlit application that takes a mathematical expression as input and evaluates it, ensuring it only accepts valid inputs.\n",
        "\n",
        "The script starts by importing the required libraries, streamlit and re. It defines a function evaluate_expression(expression) that uses a regular expression (re.match) to allow only numbers, operators (+, -, *, /), and parentheses in the input. If the input is valid, it attempts to evaluate the expression using Python’s eval() function. If the evaluation fails, an error message is returned. The Streamlit app itself consists of a title, \"Simple Expression Evaluator,\" and a text input field where the user can enter a mathematical expression. Once the user inputs the expression, the result is calculated and displayed on the page. If the input contains invalid characters, the app will notify the user."
      ],
      "metadata": {
        "id": "kO2L7d_9Rm67"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "%%writefile app.py\n",
        "import streamlit as st\n",
        "import re\n",
        "\n",
        "def evaluate_expression(expression):\n",
        "    # Allow only numbers, operators, and parentheses\n",
        "    if re.match(r'^[0-9+\\-*/(). ]+$', expression):\n",
        "        try:\n",
        "            # Evaluate the expression\n",
        "            result = eval(expression)\n",
        "            return result\n",
        "        except Exception as e:\n",
        "            return f\"Error: {str(e)}\"\n",
        "    else:\n",
        "        return \"Invalid input: Only numbers and mathematical operators are allowed.\"\n",
        "\n",
        "# Streamlit app\n",
        "st.title(\"Simple Expression Evaluator\")\n",
        "\n",
        "# User input\n",
        "expression = st.text_input(\"Enter a mathematical expression:\", \"\")\n",
        "\n",
        "# Evaluate and display result\n",
        "if expression:\n",
        "    result = evaluate_expression(expression)\n",
        "    st.write(f\"Result: {result}\")"
      ],
      "metadata": {
        "id": "Aq-XOzLWRvBK"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "Just like before, we obtain the password, start the server, and then the tunnel."
      ],
      "metadata": {
        "id": "rLEnh-CFdl-R"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "!curl https://loca.lt/mytunnelpassword"
      ],
      "metadata": {
        "id": "wmMu1L6eRv_G"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "!streamlit run app.py &>/content/logs.txt &"
      ],
      "metadata": {
        "id": "9C6r3pS_RySE"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "!npx localtunnel --port 8501"
      ],
      "metadata": {
        "id": "nleI8bVhR2_L"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "cDSVQC8y1pHi"
      },
      "source": [
        "# Module 10 Assignment\n",
        "\n",
        "You can find the first assignment here: [assignment 10](https://github.com/jeffheaton/app_generative_ai/blob/main/assignments/assignment_yourname_class10.ipynb)"
      ]
    }
  ],
  "metadata": {
    "anaconda-cloud": {},
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3 (ipykernel)",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.12.4"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}